package com.huawo.opensdk;

import android.annotation.SuppressLint
import android.app.Activity
import android.app.Application
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.graphics.BitmapFactory
import android.util.Log
import androidx.localbroadcastmanager.content.LocalBroadcastManager
import com.google.auto.service.AutoService
import com.huawo.opensdk.bean.FirmwareVersionDate
import com.huawo.opensdk.bean.QjsWatchFaceBean
import com.huawo.opensdk.bean.WatchDialLayoutBean
import com.huawo.opensdk.listener.OnConnectionStateListener
import com.huawo.opensdk.listener.OnFirmwareUpgradeListener
import com.huawo.opensdk.listener.OnWatchFaceTransListener
import com.huawo.opensdk.manager.DeviceUpgradeManager
import com.huawo.opensdk.manager.SDKInvokeException
import com.huawo.opensdk.trim.VideoTrimmerActivity
import com.huawo.opensdk.utils.CodeWrapper
import com.huawo.opensdk.utils.FileUtils
import com.huawo.opensdk.utils.SM
import com.huawo.opensdk.utils.UploadFileUtils
import com.huawo.qjs.utils.QjsUtils
import com.huawo.qjs.utils.SFSDK
import com.huawo.sdk.bluetoothsdk.BluetoothSDK
import com.huawo.sdk.bluetoothsdk.callback.ConnectCallback
import com.huawo.sdk.bluetoothsdk.core.model.Device
import com.huawo.sdk.bluetoothsdk.interfaces.callback.IntValueCallback
import com.sifli.siflicore.error.SFError
import com.sifli.siflicore.error.SFErrorCode
import com.sifli.siflicore.util.ByteUtil
import com.sifli.siflidfu.Protocol
import com.sifli.siflidfu.SifliDFUService
import com.sifli.watchfacesdk.manager.SFWatchfaceFilePushManagerCallback
import io.reactivex.Completable
import io.reactivex.Observable
import io.reactivex.schedulers.Schedulers
import java.io.File
import java.util.Date
import java.util.Locale
import java.util.concurrent.TimeUnit


@AutoService(IHealthDevice::class)
class HwSifliDevice(val sApplication: Application) : IHealthDevice {
    var TAG: String = "HwSifliDevice"
    var aMAC: String? = null
    var listener: OnConnectionStateListener? = null

    var firmwareUpgradeListener: OnFirmwareUpgradeListener? = null


    init {
        ApplicationHolder.sApplication = sApplication
    }

    override fun setOnConnectionStateListener(listener: OnConnectionStateListener?) {
        if (this.listener == null && listener != null)
            this.listener = listener
    }

    override fun connect(mac: String) {
        aMAC = mac
        BluetoothSDK.connect(mac, object : ConnectCallback() {
            @SuppressLint("CheckResult")
            override fun onSuccess(device: Device) {
                SM.spSaveString(sApplication, "MAC", mac)

                var oldDevice = BluetoothSDK.getConnectedDevice();
                var isBound = (oldDevice != null && (oldDevice.mac.equals(mac)));

                BluetoothSDK.getBindState(object : IntValueCallback() {
                    override fun onSuccess(state: Int) {
                        if (state != 1) {
                            isBound = false
                        }
                        bindDeviceOrCallbackConnectionResult(isBound)
                    }

                    override fun onFail(code: Int) {
                        isBound = false
                        bindDeviceOrCallbackConnectionResult(false)
                    }
                })
                //初始化表盘逻辑控制
                SM.spSaveBoolean(sApplication, "doing", false)
                SM.spSaveBoolean(sApplication, "SyncCustomWatchFace", false)
            }

            override fun onFail(code: Int) {
//                SM.spSaveString(sApplication, "MAC", "")
                if (listener != null)
                    listener?.onStateChanged(OnConnectionStateListener.ConnectState.STATE_DISCONNECTED)
            }
        })
    }
    @SuppressLint("CheckResult")
    fun bindDeviceOrCallbackConnectionResult(isBound: Boolean) {
        val connectDevice = DeviceConnectManager.getConnectDevice()
        if (!isBound || connectDevice == null) {
            Log.e(TAG, "bind --- 未绑定")
            CodeWrapper.speedLimit(
                true, DeviceSDKProxy.bind()
            ).subscribeOn(Schedulers.io()).subscribe({
                if (listener != null)
                    listener?.onStateChanged(OnConnectionStateListener.ConnectState.STATE_CONNECTED)
                Log.e(TAG, "bind --- onSuccess")

            }) { error ->Log.e(TAG, "bind --- onFail") }
        } else {
            Log.e(TAG, "bind --- 已绑定")
            if (listener != null)
                listener?.onStateChanged(OnConnectionStateListener.ConnectState.STATE_CONNECTED)
        }
    }

    @SuppressLint("CheckResult")
    override fun disconnect() {
        if (aMAC != null) {
            Log.e(TAG, "disconnect --- start")
            CodeWrapper.speedLimit(
                true, DeviceSDKProxy.disconnect()
            ).subscribeOn(Schedulers.io()).subscribe({

                Log.e(TAG, "disconnect --- onSuccess")
            }) { error -> Log.e(TAG, "disconnect --- onFail") }
        } else {
            Log.e(TAG, "aMAC为null")
        }
    }

    @SuppressLint("CheckResult")
    override fun removeBond() {
        if (aMAC != null) {
            Log.e(TAG, "removeBond --- start")
            CodeWrapper.speedLimit(
                true, DeviceSDKProxy.unbind(aMAC)
            ).subscribeOn(Schedulers.io()).subscribe({
                DeviceConnectManager.setConnectDevice(null)

                Log.e(TAG, "removeBond --- onSuccess")
            }) { error ->   Log.e(TAG, "removeBond --- onFail") }
        } else {
            Log.e(TAG, "aMAC为null")
        }
    }

    @SuppressLint("CheckResult")
    override fun syncTime() {
        CodeWrapper.speedLimit(true, DeviceSDKProxy.setDeviceTime(Date()))
            .subscribeOn(Schedulers.io())
            .subscribe({
                Log.e(TAG, "syncTime --- onSuccess")
            }) { error -> Log.e(TAG, "syncTime --- onFail") }
    }

    @SuppressLint("CheckResult")
    override fun syncLanguage() {
        CodeWrapper.speedLimit(true, DeviceSDKProxy.setLanguage(Locale.getDefault().language))
            .subscribeOn(Schedulers.io())
            .subscribe({
                Log.e(TAG, "setLanguage --- onSuccess")
            }) { error -> Log.e(TAG, "setLanguage --- onFail") }
    }

    @SuppressLint("CheckResult")
    override fun findDevice() {
        CodeWrapper.speedLimit(true, DeviceSDKProxy.findDevice())
            .subscribeOn(Schedulers.io())
            .subscribe({
                Completable.complete().delay(3, TimeUnit.SECONDS)
                    .subscribe {}
            }) { error -> Log.e(TAG, "findDevice --- onFail") }
    }

    @SuppressLint("CheckResult")
    override fun sendDialBinFile(file: File, listener: OnWatchFaceTransListener) {
        val bytes = UploadFileUtils.readFile(file)
        DeviceSDKProxy.setOnlineWatchface(bytes, file.absolutePath)
            .subscribe({ progress ->
                listener.onTransProgressChanged(progress.toInt())
            }, { error ->
                listener.onTransError(0, error.toString())
            }) {
                listener.onTransCompleted()
            }

    }

    override fun sendAbortDialBinFile() {
        SFSDK.getInstance().cleanUp()
        SFSDK.getInstance().stop()
    }

    override fun sendCustomWatchDialFile(
        watchDialLayoutBean: WatchDialLayoutBean,
        imagePath: String,
        onTransListener: OnWatchFaceTransListener
    ) {
        SM.spSaveBoolean(sApplication, "SyncCustomWatchFace", true)
        DeviceSDKProxy.SyncCustomWatchFace(sApplication, QjsWatchFaceBean(
            watchDialLayoutBean.index,
            watchDialLayoutBean.width,
            watchDialLayoutBean.height,
            watchDialLayoutBean.textColor,
            if (imagePath.contains(".gif")) null else BitmapFactory.decodeFile(imagePath),
            if (imagePath.contains(".gif")) File(imagePath) else null,
            BitmapFactory.decodeFile(imagePath),
            watchDialLayoutBean.widgetList,
            watchDialLayoutBean.timePosition
        ), object : OnWatchFaceTransListener {
            override fun onTransProgressStarting() {
                onTransListener.onTransProgressStarting()
                Log.e("SyncCustomWatchFace", "onTransProgressStarting")
            }

            override fun onTransProgressChanged(progress: Int) {
                onTransListener.onTransProgressChanged(progress)
                Log.e("SyncCustomWatchFace", "onTransProgressChanged" + progress)
            }

            override fun onTransCompleted() {
                onTransListener.onTransCompleted()
                Log.e("SyncCustomWatchFace", "onTransCompleted")
            }

            override fun onTransError(errorCode: Int, cause: String) {
                onTransListener.onTransError(0, cause)
                Log.e("SyncCustomWatchFace", errorCode.toString())
                Log.e("SyncCustomWatchFace", cause)
            }

            override fun onInstallStateChange(isInstall: Boolean) {
                onTransListener.onInstallStateChange(isInstall)
                Log.e("SyncCustomWatchFace", "onInstallStateChange" + isInstall)
            }


        }
        )
    }

    override fun sendAbortTransCustomDial() {
        SM.spSaveBoolean(sApplication, "SyncCustomWatchFace", false)
        SFSDK.getInstance().cleanUp()
        SFSDK.getInstance().stop()
    }

    override fun queryFirmwareVersion(): Triple<Int, String, String> {
        try {
            val firmwareVersionDate: FirmwareVersionDate =
                DeviceSDKProxy.getFirmwareVersionDate().timeout(60, TimeUnit.SECONDS).blockingGet()
            return Triple(
                firmwareVersionDate.updateStatus,
                firmwareVersionDate.old_version,
                firmwareVersionDate.new_verson
            )
        } catch (e: Exception) {
            Log.e("queryFirmwareVersion", "queryFirmwareVersion--  error")
        }
        return Triple(
            1,
            "",
            "",
        )

    }

    private var broadcastManager: LocalBroadcastReceiver? = null
    private fun register() {
//        context.registerReceiver(receiver, intentFilter);
        if (broadcastManager == null) {
            broadcastManager = LocalBroadcastReceiver()
            val intentFilter = IntentFilter()
            intentFilter.addAction(SifliDFUService.BROADCAST_DFU_LOG)
            intentFilter.addAction(SifliDFUService.BROADCAST_DFU_STATE)
            intentFilter.addAction(SifliDFUService.BROADCAST_DFU_PROGRESS)
            LocalBroadcastManager.getInstance(sApplication)
                .registerReceiver(broadcastManager!!, intentFilter)
        }
    }

    fun unregister() {
//        context.unregisterReceiver(receiver);
        if (broadcastManager != null) {
            LocalBroadcastManager.getInstance(sApplication).unregisterReceiver(broadcastManager!!)
            broadcastManager = null
        }
    }

    override fun setOnFirmwareUpgradeListener(listener: OnFirmwareUpgradeListener?) {
        if (listener != null) {
            register()
            this.firmwareUpgradeListener = listener
        }

    }

    @SuppressLint("CheckResult")
    override fun sendStartFirmwareUpgrade(file1: File, file2: File) {
//        if (DeviceUpgradeManager.getDeviceUpgradeInfo() != null) {
//            var once = false
        if (file1.exists() && file2.exists()) {
            Log.e("sendStartFirmwareUpgrade","file1 OR file2 is null")
            return
        }
        var lastProgress = 0.00f
        DeviceUpgradeManager.upgrade(file1,file2)
            .subscribe({ progress ->

                if (lastProgress == progress) {
                    //过滤相同进度的消息
                } else {
                    lastProgress = progress
                    firmwareUpgradeListener?.onFirmwareDownloadProgress((progress * 100).toInt())
                }

                Log.e("sendStartFirmwareUpgrade", progress.toString() + "")
            }, { throwable ->
//                    firmwareUpgradeListener?.onError(500, throwable.toString())
                Log.e("sendStartFirmwareUpgrade", throwable.toString())
            }
            ) {
                Log.e("sendStartFirmwareUpgrade", "onFirmwareDownloadComplete")
                firmwareUpgradeListener?.onFirmwareDownloadComplete()
                firmwareUpgradeListener?.onUpgradeProgressStarting()
            }
        if (firmwareUpgradeListener != null)
            firmwareUpgradeListener?.onFirmwareDownloadStarting()
//        } else {
//            if (firmwareUpgradeListener != null)
//                firmwareUpgradeListener?.onError(400, "已经是最新版本了")
//        }
    }

    override fun sendAbortFirmwareUpgrade() {
        if (firmwareUpgradeListener != null)
            firmwareUpgradeListener?.onUpgradeAborted()
    }

    override fun videoToGif(context: Activity) {
        VideoTrimmerActivity.call(
            context,
            context.cacheDir.absolutePath.toString() + "/test.mp4",
            666
        )
    }
    var previousProgress = 0

    /**
     * context :Context
     * fileList : 图片绝对路径 (List<String>)
     * indexList : 文件名   1 , 2, 3 (List<Int>)
     */
    @SuppressLint("CheckResult")
    override fun sendStartPicture(context: Activity,fileList : List<String>,indexList : List<Int>) {

        Observable.fromCallable<String> {
            QjsUtils.allChangeToBin(
                context,
                fileList,
                480,
                480,
                indexList
            )
        }
            .subscribeOn(Schedulers.io())
            .subscribe({ zipPath: String? ->

                SFSDK.getInstance().pushWatchface(
                    SM.spLoadStringno(ApplicationHolder.sApplication, "MAC"),
                    3,
                    zipPath,
                    true,
                    object : SFWatchfaceFilePushManagerCallback {
                        override fun onManagerStatusChanged(status: Int) {
                            /**
                             * 0为空闲，1，连接中，2工作中
                             */

                        }

                        override fun onProgress(currentBytes: Long, totalBytes: Long) {
                            var progress = 0
                            if (totalBytes > 0) {
                                val percent = currentBytes.toDouble() / totalBytes
                                progress = (percent * 100).toInt()
                            }
                            if (progress == previousProgress) {
                            } else {
                                previousProgress = progress
                            }
                        }

                        override fun onComplete(success: Boolean, error: SFError?) {
                            Log.e("sendStartPicture","Picture==manager====success===$success==error==$error")
                            if (success) {

                            } else {
                                if (error != null) {
                                    var deviceErrorCode = error.deviceErrorCode
                                    var code = error.code
                                    if (code == SFErrorCode.SF_DEVICE_ERROR_CODE) {
                                        deviceErrorCode = translateCode(deviceErrorCode)
                                        val sdkInvokeException = SDKInvokeException(deviceErrorCode)
                                    } else {
                                        code = translateCode(code)
                                        val sdkInvokeException = SDKInvokeException(deviceErrorCode)
                                    }
                                } else {
                                    Log.e("sendStartPicture","Picture==manager====isCancelBySelf==22222=")
                                }
                            }
                            SFSDK.getInstance().cleanUp()
                        }
                    })
            }
            ) { throwable: Throwable? ->
                Log.i("【OTA - Picture】","Picture==是否处于OTA状态==compressFilesToZip===throwable")
            }
    }

    /**
     * context :Context
     * fileList : 图片绝对路径 (List<String>)
     */
    @SuppressLint("CheckResult")
    override fun sendStartMusic(context: Activity,fileList : List<String>) {
        Observable.fromCallable<String> {
            FileUtils.compressFilesToZip(context, fileList)
        }
            .subscribeOn(Schedulers.io())
            .subscribe({ zipPath: String? ->
                Log.e("【OTA - Music】","MUSIC==ipPath====zipPath===$zipPath")

                SFSDK.getInstance().pushWatchface(
                    SM.spLoadStringno(ApplicationHolder.sApplication, "MAC"),
                    4,
                    zipPath,
                    true,
                    object : SFWatchfaceFilePushManagerCallback {
                        override fun onManagerStatusChanged(status: Int) {
                            /**
                             * 0为空闲，1，连接中，2工作中
                             */

                        }

                        override fun onProgress(currentBytes: Long, totalBytes: Long) {
                            var progress = 0
                            if (totalBytes > 0) {
                                val percent = currentBytes.toDouble() / totalBytes
                                progress = (percent * 100).toInt()
                            }
                            if (progress == previousProgress) {
                            } else {
                                previousProgress = progress
                            }
                        }

                        override fun onComplete(success: Boolean, error: SFError?) {
                            Log.e("【OTA - Music】","Music==manager====success===$success==error==$error")
                            if (success) {

                            } else {
                                if (error != null) {
                                    var deviceErrorCode = error.deviceErrorCode
                                    var code = error.code
                                    if (code == SFErrorCode.SF_DEVICE_ERROR_CODE) {
                                        deviceErrorCode = translateCode(deviceErrorCode)
                                        val sdkInvokeException = SDKInvokeException(deviceErrorCode)
                                    } else {
                                        code = translateCode(code)
                                        val sdkInvokeException = SDKInvokeException(deviceErrorCode)
                                    }
                                } else {
                                    Log.e("【OTA - Music】","Music==manager====isCancelBySelf==22222=")
                                }
                            }
                            SFSDK.getInstance().cleanUp()
                        }
                    })
            }
            ) { throwable: Throwable? ->
                Log.i("【OTA - Music】","Music==是否处于OTA状态==compressFilesToZip===throwable")
            }
    }

    inner class LocalBroadcastReceiver() : BroadcastReceiver() {
        var lastProgress = 0.0f
        override fun onReceive(context: Context, intent: Intent) {
            val action = intent.action
            when (action) {
                SifliDFUService.BROADCAST_DFU_PROGRESS -> {
                    /**
                     * Progress是0~100的整数
                     * 如果是nand升级，资源(zip)和hcpu(bin)的进度是分开的，
                     * 用PROGRESS_TYPE_IMAGE和PROGRESS_TYPE_FILE区分。
                     */
                    val progress = intent.getIntExtra(SifliDFUService.EXTRA_DFU_PROGRESS, 0)
                    val type = intent.getIntExtra(SifliDFUService.EXTRA_DFU_PROGRESS_TYPE, 0)
                    val progressFloat = progress / 100f
                    Log.i("【OTA - 更新】", "type==$type==当前传递的进度==$progressFloat")
                    if (lastProgress == progressFloat) {
                        //过滤相同进度的消息
                        return
                    } else {
                        lastProgress = progressFloat
                        firmwareUpgradeListener?.onUpgradeProgressChanged((progressFloat * 100).toInt())
                    }
                }

                SifliDFUService.BROADCAST_DFU_LOG -> {
                    val logMessage = intent.getStringExtra(SifliDFUService.EXTRA_LOG_MESSAGE)
                    Log.i("【OTA - 更新】", "logMessage==$logMessage")
                }

                SifliDFUService.BROADCAST_DFU_STATE -> {
                    val dfuState = intent.getIntExtra(SifliDFUService.EXTRA_DFU_STATE, 0)
                    // dfuStaeResult的值为0代表升级成功，其他值为失败
                    val dfuStateResult =
                        intent.getIntExtra(SifliDFUService.EXTRA_DFU_STATE_RESULT, 0)
                    Log.i(
                        "【OTA - 更新】",
                        "dfuStateResult==$dfuStateResult==dfuState==$dfuState"
                    )
                    when (dfuState) {
                        Protocol.DFU_SERVICE_EXIT -> if (dfuStateResult == 0) {
                            unregister()
                            firmwareUpgradeListener?.onUpgradeCompleted()
                        } else {
                            unregister()
                            firmwareUpgradeListener?.onError(400, "安装失败")
                        }
                    }
                }
            }
        }
    }

    private fun translateCode(code: Int): Int {
        var code = code
        val bytes = ByteUtil.intTo2Bytes(code)
        if (bytes[1].toInt() and 128 > 0) {
            code = code and 0x7fff
        }
        return code
    }

}
